using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;
using Microsoft.Xna.Framework.Input;
using Pavilion;
using Pavilion.GameTools;

namespace Pavilion.Locks
{
    public class KeyInput : ILock
    {
        public Keys LeftKey { get; set; }
        public Keys RightKey { get; set; }
        public bool IsKeyDown { get; set; }

        public KeyInput()
        {
            this.LeftKey = RightKey = Keys.A;
        }

        public KeyInput(bool isKeyDown, Keys leftKey, Keys rightKey)
        {
            this.LeftKey = leftKey;
            this.RightKey = rightKey;
            this.IsKeyDown = isKeyDown;
        }

        public void Deserialize(XElement lockElement, string resourceName)
        {
            this.IsKeyDown = bool.Parse(lockElement.Attribute("IsKeyDown").Value);
            this.LeftKey = (Keys)Enum.Parse(typeof(Keys), lockElement.Attribute("LeftKey").Value.ToUpper());
            this.RightKey = (Keys)Enum.Parse(typeof(Keys), lockElement.Attribute("RightKey").Value.ToUpper());
        }

        public XElement Serialize()
        {
            XElement lockElement = new XElement("Lock");

            lockElement.Add(new XAttribute("IsKeyDown", IsKeyDown));
            lockElement.Add(new XAttribute("LeftKey", LeftKey));
            lockElement.Add(new XAttribute("RightKey", RightKey));

            return lockElement;
        }

        public LockMonitorBase CreateLockMonitor(GameItem gameItem)
        {
            return new KeyInputMonitor(this);
        }

        public override string ToString()
        {
            return this.GetType().Name;
        }

        private class KeyInputMonitor : LockMonitorBase
        {
            public bool IsDisposed { get; private set; }
            private KeyInput keyInputLock;
            private KeyboardTool keyboardController;
            private PhysicalData physicalData;
            private Action leftKeyAction, rightKeyAction;

            public KeyInputMonitor(KeyInput keyInputLock)
            {
                this.keyInputLock = keyInputLock;
                leftKeyAction = () =>
                {
                    if (physicalData.IsFlippedHorizontally)
                        IsOpen = true;
                    else
                        IsOpen = false;
                };
                rightKeyAction = () =>
                {
                    if (!physicalData.IsFlippedHorizontally)
                        IsOpen = true;
                    else
                        IsOpen = false;
                };
            }

            public override void Dispose()
            {
                Deactivate();

                physicalData = null;
                keyboardController = null;
                IsDisposed = true;
            }

            public override void Load(GameItem gameItem)
            {
                this.keyboardController = gameItem.ObtainTool<KeyboardTool>();
                this.physicalData = gameItem.ObtainTool<PhysicalTypeTool>().PolygonData;

                Activate();
            }

            private void Activate()
            {
                if (keyInputLock.IsKeyDown)
                {
                    keyboardController.RegisterKeyPressed(rightKeyAction, keyInputLock.RightKey);
                    keyboardController.RegisterKeyPressed(leftKeyAction, keyInputLock.LeftKey);
                }
                else
                {
                    keyboardController.RegisterKeyReleased(rightKeyAction, keyInputLock.RightKey);
                    keyboardController.RegisterKeyReleased(leftKeyAction, keyInputLock.LeftKey);
                }

                UpdateLockStatus();
            }

            private void Deactivate()
            {
                if (keyInputLock.IsKeyDown)
                {
                    keyboardController.UnregisterKeyPressed(rightKeyAction, keyInputLock.RightKey);
                    keyboardController.UnregisterKeyPressed(leftKeyAction, keyInputLock.LeftKey);
                }
                else
                {
                    keyboardController.UnregisterKeyReleased(rightKeyAction, keyInputLock.RightKey);
                    keyboardController.UnregisterKeyReleased(leftKeyAction, keyInputLock.LeftKey);
                }
            }

            private void UpdateLockStatus()
            {
                if (physicalData.IsFlippedHorizontally)
                    IsOpen = keyboardController.GetKeyState(keyInputLock.LeftKey, keyInputLock.IsKeyDown);
                else
                    IsOpen = keyboardController.GetKeyState(keyInputLock.RightKey, keyInputLock.IsKeyDown);
            }
        }
    }
}
